/*
	Copyright (c) 2010 <copyright holders>
	This source code is licensed under The MIT License,
	see the file LICENSE for details.
	*/

#include <boost/scoped_ptr.hpp>
#include <fstream>

#include "Game.hpp"
#include "ForwardDecls.hpp"
#include "HelpDefs.hpp"
#include "netmsg.pb.h"
#include "Net.hpp"
#include "SimNetLogic.hpp"
#include "Spatial.hpp"

#ifndef WORLDMANAGER_HPP
#define WORLDMANAGER_HPP

namespace spelprog2 {
namespace sim {

enum ReplayMode {
    REPLAYMODE_NONE,
    REPLAYMODE_RECORDING,
    REPLAYMODE_PLAYBACK
};

//! Manages a world. TODO: break this up into smaller pieces to some extent, it's starting to have rather mixed responsibilities
class WorldManager : public net::NetMessageRegistry {
    HIDE_EVIL_CONSTRUCTORS(WorldManager);

    Game & game_;
    boost::scoped_ptr<file::MessageInputFile> sourceReplay_;
    boost::scoped_ptr<file::MessageOutputFile> recordingReplay_;
    boost::scoped_ptr<Landscape> landscape_;
    boost::scoped_ptr<World> world_;
    boost::scoped_ptr<WorldSignals> signals_;
    Int myPlayerId_;
    net_logic::HandleFrameUpdate * updateHandler_; //do not deallocate, this will remain valid as long as required
    Int simUpdateSeqNbr_;
    bool fullUpdates_;
    ReplayMode replayMode_;

    template <typename M, typename P>
    inline void registerWorldListener(P ptr)
    {
        game_.getNetworking().addMsgListener<M>(updateHandler_->getMessageQueuer());
        addMsgListener<M>(ptr);
    }

    void testUnitInit();
public:
    WorldManager(Game & game);
    ~WorldManager();

    void registerNetListeners();

    const World & getWorld() const          { assert(world_); return *world_.get(); }
    World & getWorld()                      { assert(world_); return *world_.get(); }
    WorldSignals & getSignals()             { assert(signals_); return *signals_.get(); }
    const Landscape & getLandscape() const  { assert(landscape_); return *landscape_; }

    void startBackground(Int seed, const std::string & filenamen);
    void startBattle(Int seed, const std::string & filename, Int myPlayerId);
    void startReplay(const std::string & filename);
    void update(float timeDelta);
    void simUpdate();

    ReplayMode getReplayMode() const { return replayMode_; }
    file::MessageInputFile & getSourceReplay();
    file::MessageOutputFile & getRecordingReplay();

    //functions relevant for clients
    Int getMyPlayerId() const { return myPlayerId_; }
    void tryMoveSquad(Int squadId, const Int2d & destination); //issues request to server
    void tryChangeFormation(Int squadId, auxmsg::Formation formation);
    void tryStopSquad(Int squadId);
};

}; //sim
}; //spelprog2

#endif //WORLDMANAGER_HPP